package com.schedule.ticker;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

public class MpscTaskQueue {

    private final AtomicReference<TimeWheel.DelayTask> head = new AtomicReference<>(null);

    // 通过cas + 自旋 实现的安全无锁并发插入
    public void pushTask(TimeWheel.DelayTask delayTask){
        while (true){
            TimeWheel.DelayTask oldhead = head.get();
            delayTask.next = oldhead;
            if(head.compareAndSet(oldhead,delayTask)){
                return;
            }
        }
    }

    // 注意这里移除消费实际上只有一个线程
    // 如果是移除我们的头节点，那么需要和我们的消费者去竞争
    // 如果是后续的节点，可以成为世外桃源，没有竞争
    public List<Runnable> removeAndReturnShouldRun(long tickTime){
        List<Runnable> result = new ArrayList<>();
        TimeWheel.DelayTask cur = head.get();
        TimeWheel.DelayTask pre = null;
        while (cur != null){
            if(cur.deadline > tickTime){
                pre = cur;
                cur = cur.next;
                continue;
            }
            TimeWheel.DelayTask next = cur.next;
            if(pre != null){
                pre.next = next;
                result.add(cur.runnable);
                cur.next = null;
                cur = next;
                continue;
            }
            // 对于头节点需要与生产者进行竞争
            if(head.compareAndSet(cur,next)){
                result.add(cur.runnable);
                cur.next = null;
                cur = next;
                continue;
            }
            // cas失败，则对我们的队列进行重新遍历
            cur = head.get();
        }
        return result;
    }
}
